package xyz.mumuwei.youthcourseserver.utils;

import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author mumuwei
 * @date 2022/4/15
 */
@Slf4j
@Component
public class QuartzUtil {

    private static QuartzUtil jobUtil;

    private Scheduler scheduler;

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public QuartzUtil(Scheduler scheduler) {
        jobUtil = this;
        this.scheduler = scheduler;
    }

    public static QuartzUtil getInstance(){
        return QuartzUtil.jobUtil;
    }

    /**
     * 创建Job
     * @param clazz 任务类
     * @param jobName 任务名称
     * @param jobGroupName 任务所在组名称
     * @param cron 表达式
     * @throws SchedulerException 异常
     */
    public void addJob(Class clazz, String jobName, String jobGroupName, String cron) throws SchedulerException {
        // 启动调度器
        scheduler.start();

        // 构建job信息
        JobDetail jobDetail = JobBuilder.newJob(clazz)
                .withIdentity(jobName, jobGroupName)
                .build();

        // 表达式调度构建器
        CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule(cron);

        // 按新的表达式构建新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, jobGroupName)
                .withSchedule(cronSchedule)
                .build();

        scheduler.scheduleJob(jobDetail, trigger);
    }

    /**
     *
     * 创建Job（带参数）
     * @param clazz 任务类
     * @param jobName 任务名称
     * @param jobGroupName 任务所在组名称
     * @param cron 表达式
     * @param params 数据
     * @throws SchedulerException 异常
     */
    public void addJob(Class clazz, String jobName, String jobGroupName, String cron, Map<String, Object> params) throws SchedulerException {
        // 启动调度器
        scheduler.start();

        // 构建job信息
        JobDetail jobDetail = JobBuilder.newJob(clazz)
                .withIdentity(jobName, jobGroupName)
                .build();

        // 表达式调度构建器
        CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule(cron);

        // 按新的表达式构建新的trigger
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(jobName, jobGroupName)
                .withSchedule(cronSchedule)
                .build();

        // 获得JobDataMap，写入数据
        trigger.getJobDataMap().putAll(params);

        scheduler.scheduleJob(jobDetail, trigger);
    }

    /**
     * 暂停任务
     * @param jobName 任务名称
     * @param jobGroupName 任务分组名称
     * @throws SchedulerException 异常
     */
    public void pauseJob(String jobName, String jobGroupName) throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey(jobName, jobGroupName));
    }

    /**
     * 继续任务
     * @param jobName 任务名称
     * @param jobGroupName 任务分组名称
     * @throws SchedulerException 异常
     */
    public void resumeJob(String jobName, String jobGroupName) throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey(jobName, jobGroupName));
    }

    /**
     * 更新任务， 只修改时间
     * @param jobName 任务名称
     * @param jobGroupName 任务分组名称
     * @param cron 任务时间
     * @throws SchedulerException 异常
     */
    public void updateJob(String jobName, String jobGroupName, String cron) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);

        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 按新的cron表达式重新构建 trigger
        trigger = trigger.getTriggerBuilder()
                .withIdentity(triggerKey)
                .withSchedule(scheduleBuilder)
                .build();

        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 更新任务（即修改时间， 有修改数据）
     * @param jobName 任务名称
     * @param jobGroupName 任务分组名称
     * @param cron 任务执行时间
     * @param params 携带参数
     * @throws SchedulerException 异常
     */
    public void updateJob(String jobName, String jobGroupName, String cron, Map<String, Object> params) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);

        // 表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 按新的cron表达式重新构建 trigger
        trigger = trigger.getTriggerBuilder()
                .withIdentity(triggerKey)
                .withSchedule(scheduleBuilder)
                .build();

        // 修改map
        trigger.getJobDataMap().putAll(params);

        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 更新任务数据
     * @param jobName 任务名称
     * @param jobGroupName 任务分组名称
     * @param params 任务数据
     * @throws SchedulerException 异常
     */
    public void updateJob(String jobName, String jobGroupName, Map<String, Object> params) throws SchedulerException {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);

        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

        // 修改map
        trigger.getJobDataMap().putAll(params);

        // 按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, trigger);
    }

    /**
     * 删除任务
     * @param jobName 任务名称
     * @param jobGroupName 任务分组名称
     * @throws SchedulerException 异常
     */
    public void deleteJob(String jobName, String jobGroupName) throws SchedulerException {
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobName, jobGroupName));
        scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));
    }

    /**
     * 启动所有定时任务
     * @throws SchedulerException 异常
     */
    public void startAllJobs() throws SchedulerException {
        scheduler.start();
    }

    /**
     * 关闭所有定时任务
     * @throws SchedulerException 异常
     */
    public void shutdownAllJobs() throws SchedulerException {
        if (!scheduler.isShutdown()) {
            scheduler.shutdown();
        }
    }

    public List<Map<String, Object>> getAllJob() throws SchedulerException {
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
        List<Map<String, Object>> jobList = new ArrayList<>();
        for (JobKey jobKey : jobKeys) {
            List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
            for (Trigger trigger : triggers) {
                Map<String, Object> job = new HashMap<>(8);
                job.put("jobName", jobKey.getName());
                job.put("jobGroupName", jobKey.getGroup());
                job.put("trigger", trigger.getKey());
                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                job.put("jobStatus", triggerState.name());
                if (trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    String cronExpression = cronTrigger.getCronExpression();
                    job.put("cronExpression", cronExpression);
                }
                jobList.add(job);
            }
        }
        return jobList;
    }
}
